<?php  if ( ! defined('EXT')) exit('No direct script access allowed');

/**
 * Weblog Extended
 *
 * An ExpressionEngine Extension that make some modifications
 * on the control panel, adding new resources and improving
 * the visualization of the weblogs.
 *
 * @package		ExpressionEngine
 * @author		Mozart Petter
 * @copyright	Copyright (c) 2008, Mozart Petter.
 * @license		http://creativecommons.org/licenses/by-sa/2.5/br/deed.en_US
 * @link		http://projects.mozartpetter.com/projects/show/eewextended
 * @filesource
 * 
 * This work is licensed under the Creative Commons Attribution-Share Alike 2.5 Brazil.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/br/deed.en_US
 */
class Weblog_Extended
{
	
	/**
	 * Extension settings.
	 */
	var $settings 	= array();
	
	var $name            = 'Weblog Extended';
    var $version         = '0.7.1';
    var $description     = 'An ExpressionEngine Extension that make some modifications on the control panel, adding new resources and improving the visualization of the weblogs';
    var $settings_exist  = 'y';
    var $docs_url        = '';
	
	/**
	 * @private
	 * The current site ID.
	 */
	var $site_id = null;
	
	/**
	 * @private
	 * The editor type.
	 */
	var $editor_type = 'wysiwyg';
	
	/**
	 * Constructor
	 * 
	 * @param $settings Object[optional]
	 * @return 
	 */
	public function Weblog_Extended($settings = '')
	{
		$this->settings = $settings;
	}
	
	/****************************************************************************
	 * SYSTEM FUNCTIONS															*
	 ****************************************************************************/
	
	/**
	 * Called when the extension is activated from the extensions panel.
	 * 
	 * @return void
	 */
	public function activate_extension()
	{
	    global $DB;
	    
		// Extension Hooks.
		$hooks = array(
			'publish_admin_edit_field_extra_row' => 'publish_admin_edit_field_extra_row',
			'publish_form_field_unique'	=> 'publish_form_field_unique',
			'show_full_control_panel_end' => 'show_full_control_panel_end'
		);
		
		$default_settings = serialize(
			array(
				'wysiwyg_enabled' => 'true',
				'wysiwyg_folder_path' => 'scripts/fckeditor/',
				'wysiwyg_script_path' => 'scripts/fckeditor/fckeditor.js',
				'wysiwyg_config_path' => "",
				'wysiwyg_config_toolbarset' => "Default",
				'wextended_delete_tables' => 'false'
			)
		);
		
		// Checking if the blog_parent column already exists.
		$query = $DB->query("SELECT 
							 	COLUMN_NAME 
							 FROM 
							 	INFORMATION_SCHEMA.COLUMNS 
							 WHERE 
							 	COLUMN_NAME = 'blog_parent' 
							 AND 
							 	TABLE_NAME = 'exp_weblogs' 
							 AND 
							 	TABLE_SCHEMA = '{$DB->database}'
							");
		
		// If don't exists.
		if ($query->num_rows == 0)
		{
			// Adds the blog_parent column on exp_weblogs.
			$DB->query("ALTER TABLE 
							exp_weblogs 
						ADD 
							blog_parent 
						INT NOT NULL DEFAULT '0'
					");
		}
		
		// Checking if the blog_status column already exists.
		$query = $DB->query("SELECT 
							 	COLUMN_NAME 
							 FROM 
							 	INFORMATION_SCHEMA.COLUMNS 
							 WHERE 
							 	COLUMN_NAME = 'blog_status' 
							 AND 
							 	TABLE_NAME = 'exp_weblogs' 
							 AND 
							 	TABLE_SCHEMA = '{$DB->database}'
							");
		
		// If don't exists.
		if ($query->num_rows == 0)
		{
			// Adds the blog_status column on exp_weblogs.
			$DB->query("ALTER TABLE 
							exp_weblogs 
						ADD 
							blog_status 
						VARCHAR( 20 ) NOT NULL DEFAULT 'enabled'
					");
		}
		
		// Checking if the blog_order column already exists.
		$query = $DB->query("SELECT 
							 	COLUMN_NAME 
							 FROM 
							 	INFORMATION_SCHEMA.COLUMNS 
							 WHERE 
							 	COLUMN_NAME = 'blog_order' 
							 AND 
							 	TABLE_NAME = 'exp_weblogs' 
							 AND 
							 	TABLE_SCHEMA = '{$DB->database}'
							");
		
		// If don't exists.
		if ($query->num_rows == 0)
		{
			// Adds the blog_order column on exp_weblogs.
			$DB->query("ALTER TABLE 
							exp_weblogs 
						ADD 
							blog_order 
						INT( 4 ) UNSIGNED NOT NULL
					");
		}
		
		foreach ($hooks as $hook => $method)
		{
			// Registering extension.
		    $DB->query($DB->insert_string('exp_extensions',
		                                  array(
		                                        'extension_id' => '',
		                                        'class'        => get_class($this),
		                                        'method'       => $method,
		                                        'hook'         => $hook,
		                                        'settings'     => $default_settings,
		                                        'priority'     => 15,
		                                        'version'      => $this->version,
		                                        'enabled'      => "y"
		                                      )
		                                 )
									);
		}
		
	}
	
	/**
	 * Called when deactivating this extension.
	 * 
	 * @return void
	 */
	public function disable_extension()
	{
	    global $DB, $PREFS;
	    
		// Getting the setting of this extension.
		$query = $DB->query("SELECT
								settings
							FROM
								exp_extensions
							WHERE
								class = '" . get_class($this) . "'
							LIMIT 1
							");
		
		$settings = unserialize($query->result[0]['settings']);
		
		// Removing the extension register.
	    $DB->query("DELETE FROM 
						exp_extensions 
					WHERE 
						class = '" . get_class($this) . "'
					");
		
		// If the user sets to remove the tables.
		if ($settings['wextended_delete_tables'] == "true")
		{
			// Removing the blog_status column from exp_weblogs.
			$DB->query("ALTER TABLE 
							exp_weblogs 
						DROP 
							blog_status
						");
			
			// Removing the blog_parent column from exp_weblogs.
			$DB->query("ALTER TABLE 
							exp_weblogs 
						DROP 
							blog_parent
						");
			
			// Removing the blog_order column from exp_weblogs.
			$DB->query("ALTER TABLE 
							exp_weblogs 
						DROP 
							blog_order
						");
		}
		
	}
	
	/**
	 * 
	 * 
	 * @return 
	 * @param $current Object[optional]
	 */
	public function update_extension($current = '')
	{
		
	}
	
	/**
	 * Returns the settings form.
	 * 
	 * @return 
	 */
	public function settings()
	{
		$settings = array();
		
		// Use the WYSIWYG editor?
		$settings['wysiwyg_enabled'] = array('r', array('true' => 'yes', 'false' => 'no'), 'true');
		
		$settings['wysiwyg_folder_path'] = "scripts/fckeditor/";
		$settings['wysiwyg_script_path'] = "scripts/fckeditor/fckeditor.js";
		$settings['wysiwyg_config_path'] = "";
		$settings['wysiwyg_config_toolbarset'] = "Default";
		
		$settings['wextended_delete_tables'] = array('r', array('true' => 'yes', 'false' => 'no'), 'false');
		
		return $settings;
	}
	
	/****************************************************************************
	 * CONTROL PANEL FUNCTIONS													*
	 ****************************************************************************/
	
	/**
	 * Make changes on the blog admin.
	 * 
	 * @return String
	 * @param $out String The HTML code of the panel.
	 */
	private function blog_admin_panel($out)
	{
		global $IN;
		
		switch ($IN->GBL('P'))
		{
			// Showing the blog list.
			case "blog_list":
			case "create_blog":
				
				$out = $this->modify_blog_list($out);
			
			break;
			
			// When changing the blog order.
			case "blog_order":
				
				$this->change_weblog_order();
				
			break;
			
			// When changing the blog status.
			case "blog_status":
				
				$this->change_weblog_status();
				
			break;
			
			// When changing an existent weblog.
			case "blog_prefs":
			case "update_preferences":
				
				// The current weblog id.
				$weblog = $IN->GBL('weblog_id');
				
				// Creating the select status field.
				$out = $this->create_weblog_status_field($weblog, $out);
				
				// Creating the select parent field.
				$out = $this->blog_prefs_create_parent_field($weblog, $out);
				
				// If the update and finish action has been executed, show the modified list.
				if (isset($_REQUEST['return'])) $out = $this->modify_blog_list($out);
				
			break;
			
			// When a weblog is created.
			case "create_blog":
			
				// The new weblog list, with new features. :)
				$out = $this->modify_blog_list($out);
			
			break;
			
			// When a weblog is deleted.
			case "delete":
				
				// The new weblog list, with new features. :)
				$out = $this->modify_blog_list($out);
				
			break;
			
			// When creating a new weblog.
			case "new_weblog":
				
				// Creating the select parent field.
				$out = $this->new_blog_create_parent_field($out);
				
			break;
			
			// When displaying the custom field list.
			case "field_editor":
			case "update_weblog_fields":  
			case "delete_field":
				
				// Show the WYSIWYG field type.
				$out = $this->wysiwyg_custom_field_list($out);
				
			break;
		}
		
		return $out;
	}
	
	/**
	 * Creates the select parent field when editing an existent Weblog.
	 * 
	 * @return String
	 * @param $weblog_id Number The ID of the current weblog.
	 * @param $r String The current HTML code.
	 */
	private function blog_prefs_create_parent_field($weblog_id, $r)
	{
		global $DB, $EXT, $LANG, $DSP;
		
		// If no weblog_id exists.
		if ($weblog_id == '') return $r;
		
		// Loading the language file.
		$LANG->fetch_language_file('weblog_extended');
		
		// Getting the current weblog.
		$queryC = $DB->query("SELECT 
							  	blog_parent 
							  FROM 
							  	exp_weblogs 
							  WHERE 
							  	weblog_id = $weblog_id
							");
		
		// Current weblog parent.
		$parent = $queryC->result[0]['blog_parent'];
		
		// Getting weblogs.
		$queryW = $DB->query("SELECT 
							  	weblog_id, blog_title 
							  FROM 
							  	exp_weblogs 
							  WHERE 
							  	weblog_id != $weblog_id
							  AND
							  	blog_parent = '0'
							  AND
							 	site_id = " . $this->site_id . "
							");
		
		// Result.
		$resultW = $queryW->result;
		
		// Defining the row style.
		$style = 'tableCellOne';
		
		// Creating a new TR.
		$field = $DSP->tr();
		
		// Creating a new TD.
		$field .= $DSP->table_qcell($style, $DSP->qspan('defaultBold', $LANG->line('blog_parent', 'blog_parent'))
		.$DSP->qdiv('', $LANG->line('blog_parent_info')), '50%', 'top');
		
		// Creating the select header.
		$tdd = $DSP->input_select_header('blog_parent', '', 5, '260px');
		
		$selected = false;
		
		if ($parent == "") $selected = false;
		
		// Creating the select default option.
		$tdd .= $DSP->input_select_option('', 'No Parent', $selected);
		
		// Foreach weblog.
		foreach ($resultW as $weblog)
		{
			$selected = ($parent == $weblog['weblog_id']) ? true : false; 
			
			// Creating select option.
			$tdd .= $DSP->input_select_option($weblog['weblog_id'], $weblog['blog_title'], $selected);
		}
		
		// Creating the select footer.
		$tdd .= $DSP->input_select_footer();
		
		// Creating a new TD.
		$field .= $DSP->table_qcell($style, $tdd, '50%', 'top');
		
		// Closing TR.
		$field .= $DSP->tr_c();
		
		// The new field will be added after the 'blog_description' row.
		$regex = "/(<input.*?name=.blog_description.*?>[\r\n].*?<\/td>[\r\n].*?<\/tr>)/is";
		
		// Adding the new row.
		$replace = "$1$field";
		
		// Running the regex.
		$r = preg_replace($regex, $replace, $r);
		
		return $r;
	}
	
	/**
	 * Changes the weblog order.
	 * 
	 * @return void
	 * @param $weblog_id Number[optional] The Weblog id.
	 * @param $weblog_parent Number[optional] The parent Weblog id.
	 * @param $order String[optional] The order direction: up or down?
	 */
	private function change_weblog_order($weblog_id = '', $weblog_parent = '', $order = '')
	{
		global $FNS, $DB;
		
		// Return URL.
		$return = BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_list';
		
		if ($weblog_id == '')
		{
			// Fetch required globals.
	        foreach (array('weblog_id', 'weblog_parent', 'order') as $param)
	        {
	        	if (!isset($_GET[$param]))
	        	{
					return FALSE;
	        	}
				
	        	$$param = $_GET[$param];
	        }
		}
		
		// Is the requested weblog already at the beginning/end of the list?
		$dir = ($order == 'up') ? 'asc' : 'desc';
		
		$query = $DB->query("SELECT 
							 	weblog_id, blog_title
							 FROM 
							 	exp_weblogs 
							 WHERE 
							 	blog_parent = '" . $DB->escape_str($weblog_parent) . "'
							 AND
							 	site_id = '" . $this->site_id . "'
							 ORDER BY 
								blog_order {$dir},
								weblog_id {$dir}
							 LIMIT 1
							");
		
		if ($query->row['weblog_id'] == $weblog_id)
		{
			$FNS->redirect($return);
			exit;        
		}
		
		// Fetch all the weblogs in the parent.
		$query = $DB->query("SELECT 
								weblog_id, blog_order 
							 FROM 
							 	exp_weblogs 
							 WHERE 
							 	blog_parent = '" . $DB->escape_str($weblog_parent) . "'
							 AND
							 	site_id = '" . $this->site_id . "'
							 ORDER BY 
							 	blog_order ASC,
								weblog_id ASC
							");
		
		// If there is only one weblog, there is nothing to re-order.
		if ($query->num_rows <= 1)
		{
			$FNS->redirect($return);
			exit;        
		}
		
		// Assign weblog ID numbers in an array except the weblog being shifted.
		// We will also set the position number of the weblog being shifted, which
		// we'll use in array_shift().
	
		$flag = '';
		$i = 1;
		$weblogs = array();
		
		foreach ($query->result as $row)
		{
			if ($weblog_id == $row['weblog_id'])
			{
				$flag = ($order == 'down') ? $i + 1 : $i - 1;
			}
			else
			{
				$weblogs[] = $row['weblog_id'];				
			}
			
			$i++;
		}
						
		array_splice($weblogs, ($flag -1), 0, $weblog_id);
		
		// Update the weblog order for all the weblogs within the given parent.
		$i = 1;
		
		foreach ($weblogs as $val)
		{
			$DB->query("UPDATE 
							exp_weblogs 
						SET blog_order = '$i' 
						WHERE weblog_id = '$val'
					  ");
			
			$i++;
		}
		
		// Returning...
		$FNS->redirect($return);
		exit;
	}
	
	/**
	 * 
	 * 
	 * @return 
	 * @param $weblog_id Object[optional]
	 * @param $blog_status Object[optional]
	 */
	private function change_weblog_status($weblog_id = '', $blog_status = '')
	{
		global $FNS, $DB;
		
		// Return URL.
		$return = BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_list';
		
		if ($weblog_id == '')
		{
			// Fetch required globals.
	        foreach (array('weblog_id', 'blog_status') as $param)
	        {
	        	if (!isset($_GET[$param]))
	        	{
					return FALSE;
	        	}
				
	        	$$param = $_GET[$param];
	        }
		}
		
		$blog_status = ($blog_status == 'enabled') ? 'disabled' : 'enabled';
		
		// Fetch all the weblogs in the parent.
		$query = $DB->query("UPDATE
								exp_weblogs
							SET 
								blog_status = '$blog_status'
							WHERE
								weblog_id = $weblog_id
							");
		
		// Returning to list of weblogs.
		$FNS->redirect($return);
		exit;        
	}
	
	/**
	 * Creates the select status field when editing an existent Weblog.
	 * 
	 * @return String
	 * @param $weblog_id The id of the current weblog.
	 * @param $r The HTML code.
	 */
	private function create_weblog_status_field($weblog_id, $r)
	{
		global $DB, $EXT, $LANG, $DSP;
		
		// If no weblog_id exists.
		if ($weblog_id == '') return $r;
		
		// Loading the language file.
		$LANG->fetch_language_file('weblog_extended');
		
		// Getting section info.
		$query = $DB->query("SELECT 
								blog_status 
							 FROM 
							 	exp_weblogs 
							 WHERE 
							 	weblog_id = " . $weblog_id . "
							 AND
							 	site_id = " . $this->site_id . "
							");
		
		// Result.
		$result = $query->result;
		
		// The current weblog status, if it's enabled or not.
		$isEnabled = ($result[0]['blog_status'] == "enabled") ? true : false;
		
		// Defining the row style.
		$style = 'tableCellTwo';
		
		// Creating a new TR.
		$field = $DSP->tr();
		
		// Creating a new TD.
		$field .= $DSP->table_qcell($style, $DSP->qspan('defaultBold', $LANG->line('blog_status', 'blog_status'))
		.$DSP->qdiv('', $LANG->line('blog_status_info')), '50%', 'top');
		
		// Creating the select header.
		$tdd = $DSP->input_select_header('blog_status', '', 5, '260px');
		
		// Creating the select options.
		$tdd .= $DSP->input_select_option('enabled', 'Enabled', $isEnabled);
		$tdd .= $DSP->input_select_option('disabled', 'Disabled', !$isEnabled);
		
		// Creating the select footer.
		$tdd .= $DSP->input_select_footer();
		
		// Creating a new TD.
		$field .= $DSP->table_qcell($style, $tdd, '50%', 'top');
		
		// Closing TR.
		$field .= $DSP->tr_c();
		
		// The new field will be added after the 'blog_description' row.
		$regex = "/(<input.*?name=.blog_description.*?>[\r\n].*?<\/td>[\r\n].*?<\/tr>)/is";
		
		// Adding the new row.
		$replace = "$1$field";
		
		// Running the regex.
		$r = preg_replace($regex, $replace, $r);
		
		return $r;
	}
	
	/**
	 * Creates the WYSIWYG editor on every field with the class weblog_ext_editor.
	 * 
	 * @return 
	 * @param $out Object
	 */
	private function create_wysiwyg_editor($out)
	{
		global $GBL, $IN, $DB, $REGX, $PREFS;

		// Creating the script tag with the FCK Editor.		
		$r = "\n" . '<script type="text/javascript" src="' . trim($this->settings['wysiwyg_script_path']) . '"></script>';
		
		// Placing the FCKEditor before the head tag.
		$out = str_replace("</head>", $r . "</head>", $out);
		
		// Creating the init script.
		$r .= "\n" . '
			<script type="text/javascript">
			/*<![CDATA[*/
				
				/**
				 * Returns the elements list specified by searchClass.
				 * @author http://www.dustindiaz.com/getelementsbyclass/
				 *
				 * @param searchClass String The class name.
				 * @param node
				 * @param tag
				 * @return Array
				 */
				function getElementsByClass(searchClass,node,tag) 
				{
					var classElements = new Array();
					
					if ( node == null )
						node = document;
						
					if ( tag == null )
						tag = "*";
						
					var els = node.getElementsByTagName(tag);
					var elsLen = els.length;
					var pattern = new RegExp("(^|\\\\s)"+searchClass+"(\\\\s|$)");
					
					for (i = 0, j = 0; i < elsLen; i++) 
					{
						if (pattern.test(els[i].className)) 
						{
							classElements[j] = els[i];
							j++;
						}
					}
					
					return classElements;
				}
				
				/**
				 * Creates a new FCKeditor instance on element specified by name.
				 * 
				 * @return void
				 */
				function createEditor(name, rows)
				{
					var editor = new FCKeditor(name);
					editor.BasePath = "' . $this->settings['wysiwyg_folder_path'] . '";
					editor.Config["CustomConfigurationsPath"] = "' . $this->settings['wysiwyg_config_path'] . '";
					editor.ToolbarSet = "' . $this->settings['wysiwyg_config_toolbarset'] . '";
					editor.Height = rows * 18;
					editor.ReplaceTextarea();
				}
				
				/**
				 * Switch the text areas with the class weblog_ext_editor
				 * for the WYSIWYG editor.
				 * 
				 * @return void
				 */
				function createEditors()
				{
					var editors = getElementsByClass("weblog_ext_editor");
					
					for (var i = 0; i < editors.length; i++)
					{
						createEditor(editors[i].name, editors[i].rows);
					}
				}
				
				createEditors();
				
			/*]]>*/
			</script>';
		
		$out = str_replace("</body>", $r . "</body>", $out);
		
		return $out;
	}
	
	/**
	 * Returns the children of the weblog.
	 * 
	 * @return Array
	 * @param $parent Number Id of the weblog
	 * @param $status String[optional] The weblog status (enabled/disabled);
	 */
	private function getWeblogChildren($parent, $status = '')
	{
		global $DB;
		
		// Getting the childs.
		$sql = 	"SELECT
						weblog_id, blog_title, blog_name, blog_status, blog_order, blog_parent
					FROM 
						exp_weblogs
					WHERE
						site_id	= " . $this->site_id . "
					AND
						blog_parent = $parent ";
		
		if ($status != '') $sql .= "AND blog_status = '$status' ";
					
		$sql .= "ORDER BY
					blog_order";
		
		// Executing SQL.
		$query = $DB->query($sql);
		
		return $query->result;
	}
	
	/**
	 * Modifies the publish menu, adding nested children and more.
	 * 
	 * @return 
	 * @param $out String The HTML code of the panel
	 */
	private function modify_publish_menu($out)
	{
		global $SESS, $LANG, $DSP, $DB;
		
		// Additional styles.
		$style = "
html > body #publishdropmenu ul
{
	background-color: #E1E8E9;
	position: absolute;
	margin-left: 10px;
	margin-top: -5px;
}

html > body .navCell #publishdropmenu li:hover ul
{
	display: block;
	visibility: visible;
}

#publishdropmenu li a span
{
	display: block;
	position: relative;
	float: right;
	width: 10px;
	margin-top: -20px;
	margin-right: 10px;
}
";
		
		// Getting styles.
		$regexStyle = "/(<style.?type=.text\/css.>)(.*?)(<\/style>)/is";
		
		// Adding the new row.
		$replaceStyle = "$1$2$style$3";
		
		// Running the regex.
		$out = preg_replace($regexStyle, $replaceStyle, $out);
		
		// The new publish menu HTML.
		$html = "<ul id='publishdropmenu'>";
		
		// Getting the root weblogs.
		$sql = 	"SELECT
						weblog_id, blog_title
					FROM 
						exp_weblogs
					WHERE
						blog_parent = 0
					AND
						blog_status = 'enabled'
					ORDER BY
						blog_order";
		
		$query = $DB->query($sql);
		
		// Listing only the user assigned weblogs.
		foreach ($query->result as $weblog)
		{
			if (@$SESS->userdata['assigned_weblogs'][$weblog['weblog_id']])
			{
				// Weblog children.
				$children = $this->getWeblogChildren($weblog['weblog_id'], 'enabled');
				
				$html .= "<li class='publishdropmenuinner'>";
				$html .= "<a href='".BASE.AMP."C=publish".AMP."M=entry_form".AMP."weblog_id=".$weblog['weblog_id']."' title='".$DSP->html_attribute_prep($weblog['blog_title'])."' onclick='location.href=this.href;'>";
				$html .= $DSP->html_attribute_prep($weblog['blog_title']);
				if (count($children) > 0) $html .= "<span>&raquo;</span>";
				$html .= "</a>";
				
				// If a child exists.
				if (count($children) > 0)
				{
					$html .= "<ul id='publishdropsubmenu" . $weblog['weblog_id'] . "'>";
					
					// For each child on weblog.
					foreach ($children as $child)
					{
						if ($child['blog_status'] == "enabled")
						{
							$html .= "<li class='publishdropmenuinner'>";
							$html .= "<a href='".BASE.AMP."C=publish".AMP."M=entry_form".AMP."weblog_id=".$child['weblog_id']."'>";
							$html .= $child['blog_title'];
							$html .= "</a></li>";
						}
					}
					
					$html .= "</ul>";
				}
				
				$html .= "</li>";
			}
		}
		
		// If the user can admin weblogs.
		if ($DSP->allowed_group('can_admin_weblogs'))
		{
			$html .= "<li class='publishdropmenuinner'>";
			$html .= "<a href='".BASE.AMP."C=admin".AMP."M=blog_admin".AMP."P=blog_list' title='".$LANG->line('edit_weblogs')."' onclick='location.href=this.href;'>";
			$html .= "<em>&#187;&nbsp;".$LANG->line('edit_weblogs')."</em>";
			$html .= "</a></li>";
		}
		
		$html .= "</ul>";
		
		// Getting the publish drop-down menu.
		$regex = "/(<ul.?id=.publishdropmenu.*?>.*?<\/ul>)/is";
		
		// Adding the new row.
		$replace = $html;
		
		// Running the regex, limited to 1 replacement, so only the first menu is replaced.
		$out = preg_replace($regex, $replace, $out, 1);
		
		return $out;
	}
	
	/**
	 * Changes the Weblog default list, to another that displays the child Weblogs below of it's fathers.
	 *  
	 * @return String
	 * @param $out String The HTML code of the panel.
	 */
	private function modify_blog_list($out)
	{
		global $LANG, $DSP, $DB, $PREFS, $IN;
		
		// Themes folder.
		$themes_folder = $PREFS->ini('theme_folder_url', 1);
		
		// Loading the language file.
		$LANG->fetch_language_file('weblog_extended');
		
		// Creating the new HTML Weblog list.
		$html = $DSP->qdiv('tableHeading', $LANG->line('weblog_management'));
		
		// Checking if a status message is needed.
		switch ($IN->GBL('P'))
		{
			case "create_blog":
				
				// Show the create message.
				$html .= $DSP->qdiv('box', $DSP->qdiv('itemWrapper', $DSP->qspan('success', $LANG->line('weblog_created').":").NBS.NBS.'<b>'.$_POST['blog_title'].'</b>'));
				
			break;
			
			case "delete":
				
				// Finding the deleted weblog name.
				$dregex = "/<span +class=.success. *>.*?<b>(.*?)<\/b><\/span>/";
				
				// Running the regex.
				preg_match($dregex, $r, $dmatches);
				
				// Blog title.
				$blog_title = $dmatches[1];
				
				// Show the deleted message.
				$html .= $DSP->qdiv('box', $DSP->qdiv('itemWrapper', $DSP->qspan('success', $LANG->line('weblog_deleted').":").NBS.NBS.'<b>' . $blog_title . '</b>'));
				
			break;
			
			case "update_preferences":
				
				// Show the updated message.	
				$html .= $DSP->qdiv('box', $DSP->qdiv('itemWrapper', $DSP->qspan('success', $LANG->line('weblog_updated').":").NBS.NBS.'<b>'.$_POST['blog_title'].'</b>'));
				
			break;
		}
        
		// Starting the Weblog list table.
        $html .= $DSP->table('tableBorder', '0', '', '100%');
		
		// Creating the table headers.
        $html .= $DSP->tr().
              $DSP->td('tableHeadingAlt', '20px').$LANG->line('weblog_id').$DSP->td_c().
			  $DSP->td('tableHeadingAlt', '50px').$LANG->line('weblog_order').$DSP->td_c().
              $DSP->td('tableHeadingAlt').$LANG->line('weblog_name').$DSP->td_c().
              $DSP->td('tableHeadingAlt', '').$LANG->line('weblog_short_name').$DSP->td_c().
			  $DSP->td('tableHeadingAlt', '', '4').$LANG->line('blog_status').$DSP->td_c().
              $DSP->tr_c();
        
		// Just a counter...
        $i = 0;
		
		// Getting weblogs without parents.
		$weblogs = $this->getWeblogChildren(0);
		
		// For each Weblog.
		foreach($weblogs as $parent)
		{
			// Defining the cell style.
			$style = ($i % 2) ? 'tableCellOne' : 'tableCellTwo';
          	
			$html .= $DSP->tr();
			
			// Weblog ID.
        	$html .= $DSP->table_qcell($style, $DSP->qspan('default', $parent['weblog_id']));
			
			// Order arrows images.
			$upOrderImage = '<img src="' . $themes_folder . 'cp_global_images/arrow_up.gif' . '" style="border: none;" />';
			$downOrderImage = '<img src="' . $themes_folder . 'cp_global_images/arrow_down.gif' . '" style="border: none;" />';
			
			// Order buttons.
			$html .= $DSP->table_qcell($style, $DSP->qspan('default',
				$DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_order'.AMP.'weblog_id='.$parent['weblog_id'].AMP.'weblog_parent=0'.AMP.'order=up', $upOrderImage).
				'&nbsp'.
				$DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_order'.AMP.'weblog_id='.$parent['weblog_id'].AMP.'weblog_parent=0'.AMP.'order=down', $downOrderImage)
			));
			
        	$html .= $DSP->table_qcell($style, $DSP->qspan('defaultBold', $parent['blog_title']).$DSP->nbs(5));
        	$html .= $DSP->table_qcell($style, $DSP->qspan('default', $parent['blog_name']).$DSP->nbs(5));
			
			$html .= $DSP->table_qcell($style, $DSP->qspan('default', $parent['blog_status']." ["
					.$DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_status'.AMP.'weblog_id='.$parent['weblog_id'].AMP.'blog_status='.$parent['blog_status'], 'change')."]")
					.$DSP->nbs(5));
			
        	$html .= $DSP->table_qcell($style, $DSP->anchor(
					BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_prefs'.AMP.'weblog_id='.$parent['weblog_id'], 
					$LANG->line('edit_preferences')
			));
					
        	$html .= $DSP->table_qcell($style, $DSP->anchor(
					BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=group_prefs'.AMP.'weblog_id='.$parent['weblog_id'], 
					$LANG->line('edit_groups')
			));
			
        	$html .= $DSP->table_qcell($style, $DSP->anchor(
					BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=delete_conf'.AMP.'weblog_id='.$parent['weblog_id'], 
					$LANG->line('delete')
			));
           	
			$html .= $DSP->tr_c();
			
			$i++;
			
			// Getting parent children.
			$children = $this->getWeblogChildren($parent['weblog_id']);
			
			// For each child.
			foreach ($children as $child)
			{
				// Defining the cell style.
				$style = ($i % 2) ? 'tableCellOne' : 'tableCellTwo';
			
				$html .= $DSP->tr();
				
				// Weblog Id.
            	$html .= $DSP->table_qcell($style, $DSP->qspan('default', $child['weblog_id']));
            	
				// Order buttons.
				$html .= $DSP->table_qcell($style, $DSP->qspan('default',
					$DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_order'.AMP.'weblog_id='.$child['weblog_id'].AMP.'weblog_parent='.$child['blog_parent'].AMP.'order=up', $upOrderImage).
					'&nbsp'.
					$DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_order'.AMP.'weblog_id='.$child['weblog_id'].AMP.'weblog_parent='.$child['blog_parent'].AMP.'order=down', $downOrderImage)
				));
				
				// 
				$child_image = '<img src="' . $themes_folder . 'cp_global_images/cat_marker.gif' . '" /> ';
				
				$html .= $DSP->table_qcell($style, $DSP->qspan(
					'defaultBold', '&nbsp;&nbsp;&nbsp;&nbsp;' . $child_image . $child['blog_title']) . $DSP->nbs(5)
				);
				
            	$html .= $DSP->table_qcell($style, $DSP->qspan('default', $child['blog_name']).$DSP->nbs(5));
				
				$html .= $DSP->table_qcell($style, $DSP->qspan('default', $child['blog_status']." ["
					.$DSP->anchor(BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_status'.AMP.'weblog_id='.$child['weblog_id'].AMP.'blog_status='.$child['blog_status'], 'change')."]")
					.$DSP->nbs(5));
            	
				$html .= $DSP->table_qcell($style, $DSP->anchor(
						BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=blog_prefs'.AMP.'weblog_id='.$child['weblog_id'], 
						$LANG->line('edit_preferences')
				));
            	
				$html .= $DSP->table_qcell($style, $DSP->anchor(
                                BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=group_prefs'.AMP.'weblog_id='.$child['weblog_id'], 
                                $LANG->line('edit_groups')
                              ));
            	$html .= $DSP->table_qcell($style, $DSP->anchor(
						BASE.AMP.'C=admin'.AMP.'M=blog_admin'.AMP.'P=delete_conf'.AMP.'weblog_id='.$child['weblog_id'], 
						$LANG->line('delete')
				));
	           	
				$html .= $DSP->tr_c();
				
				$i++;
			}
			
		}
		
		// tabela dos setores.
		$html .= $DSP->table_c();
		
		// The new field will be added after the 'edit_group_prefs' row.
		$regex = "/(<div.?class=.tableHeading.*?>.*?[\r\n]<\/table>.*?[\r\n]<\/div>)/is";
		
		// Adding the new row.
		$replace = "$html";
		
		// Running the regex.
		$out = preg_replace($regex, $replace, $out);
		
		return $out;
	}
	
	/**
	 * Adds the WYSIWYG field on the admin custom fields section.
	 * 
	 * @return 
	 */
	public function publish_admin_edit_field_extra_row($data, $r)
	{
		global $EXT, $LANG, $REGX;
		
		// Check if we're not the only one using this hook
		if ($EXT->last_call !== FALSE)
		{
			$r = $EXT->last_call;
		}
		
		// If the WYSIWYG editor is enabled.
		if ($this->settings['wysiwyg_enabled'] == "true")
		{
			// Is this field selected?
			$selected = ($data['field_type'] == $this->editor_type) ? " selected='selected'" : "";
			
			$option = "<option value='" . $REGX->form_prep($this->editor_type) . "'" . $selected . ">";
			$option .= $REGX->form_prep(strtoupper($this->editor_type));
			$option .= "</option>\n";
			
			$regex = "/(<select.*?name=.field_type.*?value=.select.*?[\r\n])/is";
			
			$replace = "$1$option";
			
			$r = preg_replace($regex, $replace, $r);
			
			
			$items = array(
				"date_block" => "block",
				"select_block" => "none",
				"pre_populate" => "none",
				"text_block" => "none",
				"textarea_block" => "block",
				"rel_block" => "none",
				"relationship_type" => "none",
				"formatting_block" => "none",
				"formatting_unavailable" => "block",
				"direction_available" => "block",
				"direction_unavailable" => "none"
			);
	
			$js = "$1\n\t\telse if (id == '".$this->editor_type."'){";
		
			foreach ($items as $key => $value)
			{
				$js .= "\n\t\t\tdocument.getElementById('" . $key . "').style.display = '" . $value . "';";
			}
			
			$js.= "\ndocument.field_form.field_fmt.selectedIndex = 0;\n";
			$js .= "\t\t}";
			
			
			$r = preg_replace("/(id\s*==\s*.rel.*?})/is", $js, $r);
			
			
			if (isset($data["field_type"]) && $data["field_type"] == $this->editor_type)
			{
	
				foreach ($items as $key => $value)
				{
					preg_match('/(id=.' . $key . '.*?display:\s*)block/', $r, $match);
					
					if (count($match) > 0 && $value == "none")
					{
						$r = str_replace($match[0], $match[1] . $value, $r);
					}
					else if ($value == "block")
					{
						preg_match('/(id=.' . $key . '.*?display:\s*)none/', $r, $match);
	
						if (count($match) > 0)
						{
							$r = str_replace($match[0], $match[1] . $value, $r);
						}
					}
				}
			}
			
		}
		
		return $r;
	}
	
	/**
	 * Adds the WYSIWYG field on the publish form.
	 * 
	 * @return 
	 */
	public function publish_form_field_unique($row, $field_data)
	{
		global $DSP, $EXT, $SESS;

		$r = "";

		// Check if we're not the only one using this hook.
		if($EXT->last_call !== FALSE)
		{
			$r = $EXT->last_call;
		}

		if($row["field_type"] == $this->editor_type)
		{
			$r .= $DSP->input_textarea("field_id_" . $row['field_id'], $field_data, $row['field_ta_rows'], 'weblog_ext_editor', '99%');
		}

		return $r;
	}
	
	/**
	 * Creates the parent select field when creating a new Weblog.
	 * 
	 * @return 
	 * @param $r Object
	 */
	private function new_blog_create_parent_field($r)
	{
		global $DB, $EXT, $LANG, $DSP;
		
		// Loading the language file.
		$LANG->fetch_language_file('weblog_extended');
		
		// Getting weblogs.
		$query = $DB->query("SELECT 
								weblog_id, blog_title 
							 FROM 
							 	exp_weblogs
							 WHERE
							 	blog_parent = '0'
							 AND
							 	site_id = " . $this->site_id . "
							");
		
		// Result.
		$result = $query->result;
		
		// Defining the row style.
		$style = 'tableCellTwo';
		
		// Creating a new TR.
		$field = $DSP->tr();
		
		// Creating a new TD.
		$field .= $DSP->table_qcell($style, $DSP->qspan('defaultBold', $LANG->line('blog_parent', 'blog_parent'))
		.$DSP->qdiv('', $LANG->line('blog_parent_info')), '50%', 'top');
		
		// Creating the select header.
		$tdd = $DSP->input_select_header('blog_parent', '', 5, '260px');
		
		// Creating the select default option.
		$tdd .= $DSP->input_select_option('0', 'No Parent', true);
		
		// Foreach weblog.
		foreach ($result as $weblog)
		{
			// Creating select option.
			$tdd .= $DSP->input_select_option($weblog['weblog_id'], $weblog['blog_title'], false);
		}
		
		// Creating the select footer.
		$tdd .= $DSP->input_select_footer();
		
		// Creating a new TD.
		$field .= $DSP->table_qcell($style, $tdd, '50%', 'top');
		
		// Closing TR.
		$field .= $DSP->tr_c();
		
		// The new field will be added after the 'edit_group_prefs' row.
		$regex = "/(<input.*?name=.edit_group_prefs.*?value=.n.*?>.*?[\r\n].*?<\/td>[\r\n].*?<\/tr>)/is";
		
		// Adding the new row.
		$replace = "$1$field";
		
		// Running the regex.
		$r = preg_replace($regex, $replace, $r);
		
		return $r;
	}
	
	/**
	 * Called when the show_full_control_panel_end hook is dispatched.
	 * 
	 * @return String
	 * @param $out String The HTML code of the panel. 
	 */
	public function show_full_control_panel_end($out)
	{
		global $IN, $EXT, $DB, $PREFS;

		// Check if we're not the only one using this hook.
		if ($EXT->last_call !== FALSE)
		{
			$out = $EXT->last_call;
		}
		
		// Setting the current site id.
		$this->site_id = $DB->escape_str($PREFS->ini('site_id'));
		
		switch($IN->GBL('M'))
		{
			// When on the blog_admin module.
			case "blog_admin":
				
				// Make some changes on the blog admin.
				$out = $this->blog_admin_panel($out);
				
			break;
			
			// When publishing a new content.
			case "new_entry":
			case "entry_form":
			case "edit_entry":
				
				// Creating the WYSIWYG editor.
				if ($this->settings['wysiwyg_enabled'] == "true") $out = $this->create_wysiwyg_editor($out);
				
			break;
		}
		
		// Changing the publish panel.
		$out = $this->modify_publish_menu($out);
		
		return $out;
	}
	
	/**
	 * Add the field type for the WYSIWYG fields on the Field Groups section.
	 * 
	 * @return String
	 * @param String The HTML code of the panel.
	 */
	private function wysiwyg_custom_field_list($out)
	{
		global $IN, $GBL, $DB, $REGX;
		
		// Get the table rows
		if (preg_match_all(
			"/C=admin&amp;M=blog_admin&amp;P=edit_field&amp;field_id=(\d*).*?<\/td>.*?<td.*?>.*?<\/td>.*?<\/td>/is", 
			$out, 
			$matches))
		{
			// For each field id
			foreach ($matches[1] as $key=>$field_id)
			{
				// Get the field type
				$query = $DB->query("SELECT 
									 	field_type 
									 FROM 
									 	exp_weblog_fields 
									 WHERE 
									 	field_id='" . $DB->escape_str($field_id) . "' 
									 LIMIT 1");

				// If the field type is wysiwyg
				if ($query->row["field_type"] == $this->editor_type)
				{
					$out = preg_replace(
						"/(C=admin&amp;M=blog_admin&amp;P=edit_field&amp;field_id=" . $field_id 
						. ".*?<\/td>.*?<td.*?>.*?<\/td>.*?)<\/td>/is", 
						"$1" . $REGX->form_prep(strtoupper($this->editor_type)) . "</td>", 
						$out);
				}
			}
		}
		
		return $out;
	}
	
}